package com.ego.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ego.admin.dao.SysDepartmentDao;
import com.ego.admin.po.SysDepartment;
import com.ego.admin.service.SysAdminService;
import com.ego.admin.service.SysDepartmentService;
import com.ego.common.exception.GlobalException;
import com.ego.common.vo.BaseSearchVo;
import org.omg.CORBA.SystemException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @program: ego
 * @description: 部门实现类
 * @author: KamTang
 * @create: 2023-02-23 21:32
 **/
@Service
public class SysDepartmentServiceImpl extends ServiceImpl<SysDepartmentDao, SysDepartment> implements SysDepartmentService {

    /**
     * 顶级部门父id
     */
    private static final long TOP_DEPT_PARENT_ID = 0L;

    /**
     * 顶级部门id
     */
    private static final long TOP_DEPT_ID = 1L;

    @Autowired
    private SysAdminService adminService;

    @Override
    public List<SysDepartment> list(String name) {
        // 获取所有部门
        List<SysDepartment> allDepartments = this.baseMapper.selectList(null);
        // 设置各个部门下的员工人数
        setPeopleCountToDept(allDepartments);
        QueryWrapper<SysDepartment> queryWrapper = new QueryWrapper<>();
        // 管理员列表 -> 部门下拉框需要获取部门信息
        if (name != null && !"".equals(name)) {
            queryWrapper.like("name", "%" + name + "%");

        }
        // 搜索结果
        List<SysDepartment> departments = this.baseMapper.selectList(queryWrapper);
        // 获取顶级部门，搜索时parent可能为空
        List<SysDepartment> top = departments.stream().filter(dept -> dept.getParentId() == TOP_DEPT_PARENT_ID).collect(Collectors.toList());
        // 不为空，要么搜索条件是“易购”，要么空（结果显示全部）
        if (!CollectionUtils.isEmpty(top)) {
            List<SysDepartment> topParent = allDepartments.stream()
                    .filter(dept -> dept.getParentId() == TOP_DEPT_PARENT_ID).collect(Collectors.toList());
            return toBeFatherAndSon(allDepartments, topParent);
        } else {
            // 分公司 or 部门  找出它和它的子节点
            List<SysDepartment> parents = new ArrayList<>(departments);
            if (!CollectionUtils.isEmpty(parents)) {
                // 清空所有数据
                parents.clear();
                // 搜索出来的部门，利用这些id，找到其下存在的子部门。
                List<Long> collectId = departments.stream().map(SysDepartment::getId).collect(Collectors.toList());
                for (SysDepartment department : allDepartments
                ) {
                    if (collectId.contains(department.getId())) {
                        // 为其赋予有人数的部门数据
                        parents.add(department);
                    }
                }
                return toBeFatherAndSon(allDepartments, parents);
            } else {
                // 没有找到，这里不能返回null，前端会报错。
                return parents;
            }
        }
    }

    /**
     * 统计各个部门下的总人数
     */
    private void setPeopleCountToDept(List<SysDepartment> allDepartments) {
        if (!CollectionUtils.isEmpty(allDepartments)) {
            // 获取所有顶级节点和所有父节点
            List<SysDepartment> top = allDepartments.stream()
                    .filter(department -> department.getId() == TOP_DEPT_ID).collect(Collectors.toList());
            List<SysDepartment> parents = allDepartments.stream()
                    .filter(department -> department.getParentId() == TOP_DEPT_ID)
                    .collect(Collectors.toList());
            parents.addAll(top);
            for (SysDepartment department :
                    allDepartments) {
                department.setTotal(adminService.countPeopleByDepartmentId(department.getId()));
            }
            // 设置公司总人数
            for (SysDepartment father : parents
            ) {
                int sum = 0;
                for (SysDepartment son : allDepartments
                ) {
                    if (son.getParentId().equals(father.getId()) && son.getTotal() != 0) {
                        sum += son.getTotal();
                    }
                }
                father.setTotal(sum);
            }
        }
    }

    /**
     * 封装为父子孙结构
     */
    private List<SysDepartment> toBeFatherAndSon(List<SysDepartment> departments, List<SysDepartment> parent) {
        return parent.stream().peek(dept -> dept.setChildren(getChildren(dept, departments))).collect(Collectors.toList());
    }

    /**
     * 获取子部门
     *
     * @param dept        当前部门
     * @param departments 所有部门
     * @return 当前部门的子部门
     */
    private List<SysDepartment> getChildren(SysDepartment dept, List<SysDepartment> departments) {
        return departments.stream().filter(department ->
                        department.getParentId().equals(dept.getId()))
                .peek(department -> department.setChildren(getChildren(department, departments)))
                .collect(Collectors.toList());
    }

    /**
     * 根据部门id判断是否存在子部门
     */
    private Boolean findSonDeptById(Long id) {
        QueryWrapper<SysDepartment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", id).eq("is_deleted", 0);
        int size = baseMapper.selectList(queryWrapper).size();
        return size != 0;
    }


    /**
     * 批量删除
     */
    @Override
    public void deleteBatch(Long[] ids) throws SystemException {
        // 前端没有多选删除，所以这里直接取一个id（也只有一个）
        SysDepartment department = this.baseMapper.selectById(ids[0]);
        // 数据库中没有此部门
        // 1、其他用户已经把该部门删除，页面没有刷新
        // 2、非法用户跳过前端校验
        if (department == null) {
            throw new GlobalException("该部门不存在，无法删除");
        } else if (findSonDeptById(ids[0])) {
            throw new GlobalException("该部门下有子部门，无法直接删除");
        } else if (adminService.countPeopleByDepartmentId(ids[0]) > 0) {
            throw new GlobalException("该部门下有员工，无法直接删除");
        }
        this.baseMapper.deleteById(ids[0]);
    }
}
